home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / os2 / mpegplay / main.c < prev    next >
C/C++ Source or Header  |  1997-01-01  |  15KB  |  642 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  * 
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  * 
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. #include "video.h"
  22. #include "proto.h"
  23. #include <sys/types.h>
  24. #include <signal.h>
  25. #if defined(OS2)
  26. #include "xstub.h"
  27. #elif defined(MIPS)
  28. #include <bsd/netinet/in.h>
  29. #else
  30. #include <netinet/in.h>
  31. #endif
  32.  
  33. #include "util.h"
  34. #include "dither.h"
  35.  
  36. /* Define buffer length. */
  37.  
  38. #define BUF_LENGTH 80000
  39.  
  40. /* Function return type declarations */
  41. void usage();
  42.  
  43. /* External declaration of main decoding call. */
  44.  
  45. extern VidStream *mpegVidRsrc();
  46. extern VidStream *NewVidStream();
  47.  
  48. /* Declaration of global variable to hold dither info. */
  49.  
  50. int ditherType;
  51.  
  52. /* Global file pointer to incoming data. */
  53. FILE *input;
  54.  
  55. /* End of File flag. */
  56. static int EOF_flag = 0;
  57.  
  58. /* Loop flag. */
  59. int loopFlag = 0;
  60.  
  61. /* Shared memory flag. */
  62. int shmemFlag = 0;
  63.  
  64. /* Quiet flag. */
  65. int quietFlag = 0;
  66.  
  67. /* Display image on screen? */
  68. int noDisplayFlag = 0;
  69.  
  70. /* Setjmp/Longjmp env. */
  71. jmp_buf env;
  72.  
  73.  
  74. /*
  75.  *--------------------------------------------------------------
  76.  *
  77.  * get_more_data --
  78.  *
  79.  *    Called by correct_underflow in bit parsing utilities to
  80.  *      read in more data.
  81.  *
  82.  * Results:
  83.  *    Input buffer updated, buffer length updated.
  84.  *      Returns 1 if data read, 0 if EOF, -1 if error.
  85.  *
  86.  * Side effects:
  87.  *      None.
  88.  *
  89.  *--------------------------------------------------------------
  90.  */
  91.  
  92. int 
  93. get_more_data(buf_start, max_length, length_ptr, buf_ptr)
  94.      unsigned int *buf_start;
  95.      int max_length;
  96.      int *length_ptr;
  97.      unsigned int **buf_ptr;
  98. {
  99.   
  100.   int length, num_read, i, request;
  101.   unsigned char *buffer, *mark;
  102.   unsigned int *lmark;
  103.  
  104.   if (EOF_flag) return 0;
  105.  
  106.   length = *length_ptr;
  107.   buffer = (unsigned char *) *buf_ptr;
  108.  
  109.   if (length > 0) {
  110.     memcpy((unsigned char *) buf_start, buffer, (length*4));
  111.     mark = ((unsigned char *) (buf_start + length));
  112.   }
  113.   else {
  114.     mark = (unsigned char *) buf_start;
  115.     length = 0;
  116.   }
  117.  
  118.   request = (max_length-length)*4;
  119.   
  120.   num_read = fread( mark, 1, request, input);
  121.  
  122.   /* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
  123.   {
  124.     int num_read_rounded;
  125.     unsigned char *index;
  126.  
  127.     num_read_rounded = 4*(num_read/4);
  128.  
  129.     /* this can happen only if num_read<request; i.e. end of file reached */
  130.     if( num_read_rounded < num_read )
  131.       { 
  132.      num_read_rounded = 4*( num_read/4+1 );
  133.      /* fill in with zeros */
  134.      for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
  135.      /* advance to the next 4-byte boundary */
  136.      num_read = num_read_rounded;
  137.       }
  138.   }
  139.   
  140.   if   (num_read < 0) {
  141.     return -1;
  142.   }
  143.   else if (num_read == 0) {
  144.     *buf_ptr = buf_start;
  145.     
  146.     /* Make 32 bits after end equal to 0 and 32
  147.        bits after that equal to seq end code
  148.        in order to prevent messy data from infinite
  149.        recursion.
  150.     */
  151.  
  152.     *(buf_start + length) = 0x0;
  153.     *(buf_start + length+1) = SEQ_END_CODE;
  154.  
  155.     EOF_flag = 1;
  156.     return 0;
  157.   }
  158.  
  159.   lmark = (unsigned int *) mark;
  160.  
  161.   num_read = num_read/4;
  162.  
  163.   for (i=0; i<num_read; i++) {
  164.     *lmark = htonl(*lmark);
  165.     lmark++;
  166.   }
  167.  
  168.   *buf_ptr = buf_start;
  169.   *length_ptr = length + num_read;
  170.  
  171.   return 1;
  172. }
  173.  
  174. /*
  175.  *--------------------------------------------------------------
  176.  *
  177.  * int_handler --
  178.  *
  179.  *    Handles Cntl-C interupts..
  180.  *
  181.  * Results:
  182.  *    None.
  183.  *
  184.  * Side effects:
  185.  *    None.
  186.  *
  187.  *--------------------------------------------------------------
  188.  */
  189.  
  190. void
  191. /* @@@ AK, Should properly do prototype for OS/2 signal handlers */
  192. #if defined(OS2)
  193. int_handler(int x)
  194. #else
  195. int_handler()
  196. #endif
  197. {
  198.   if (!quietFlag) {
  199.     fprintf(stderr, "Interrupted!\n");
  200.   }
  201.   if (curVidStream != NULL)
  202.     DestroyVidStream(curVidStream);
  203.   exit(1);
  204. }
  205.  
  206.  
  207. /*
  208.  *--------------------------------------------------------------
  209.  *
  210.  * main --
  211.  *
  212.  *    Parses command line, starts decoding and displaying.
  213.  *
  214.  * Results:
  215.  *    None.
  216.  *
  217.  * Side effects:
  218.  *    None.
  219.  *
  220.  *--------------------------------------------------------------
  221.  */
  222.  
  223. void
  224. main(argc, argv)
  225.      int argc;
  226.      char **argv;
  227. {
  228.  
  229.   char *name;
  230.   static VidStream *theStream;
  231.   int mark;
  232.   int i;
  233.  
  234.   mark = 1;
  235.   argc--;
  236.  
  237.   name = "";
  238.   input = stdin;
  239.   ditherType = ORDERED2_DITHER;
  240.   LUM_RANGE = 8;
  241.   CR_RANGE = CB_RANGE = 4;
  242.   noDisplayFlag = 0;
  243.  
  244. #ifdef SH_MEM
  245.   shmemFlag = 1;
  246. #endif
  247.  
  248.   while (argc) {
  249.     if (strcmp(argv[mark], "-nop") == 0) {
  250.       TogglePFlag();
  251.       argc--; mark++;
  252.     } else if (strcmp(argv[mark], "-nob") == 0) {
  253.       ToggleBFlag();
  254.       argc--; mark++;
  255.     } else if (strcmp(argv[mark], "-display") == 0) {
  256.       name = argv[++mark];
  257.       argc -= 2; mark++;
  258.     } else if (strcmp(argv[mark], "-dither") == 0) {
  259.       argc--; mark++;
  260.       if (argc < 1) {
  261.     perror("Must specify dither option after -dither flag");
  262.     usage(argv[0]);
  263.       }
  264.       if (strcmp(argv[mark], "hybrid") == 0) {
  265.     argc--; mark++;
  266.     ditherType = HYBRID_DITHER;
  267.       } else if (strcmp(argv[mark], "hybrid2") == 0) {
  268.     argc--; mark++;
  269.     ditherType = HYBRID2_DITHER;
  270.       } else if (strcmp(argv[mark], "fs4") == 0) {
  271.     argc--; mark++;
  272.     ditherType = FS4_DITHER;
  273.       } else if (strcmp(argv[mark], "fs2") == 0) {
  274.     argc--; mark++;
  275.     ditherType = FS2_DITHER;
  276.       } else if (strcmp(argv[mark], "fs2fast") == 0) {
  277.     argc--; mark++;
  278.     ditherType = FS2FAST_DITHER;
  279.       } else if (strcmp(argv[mark], "hybrid2") == 0) {
  280.     argc--; mark++;
  281.     ditherType = HYBRID2_DITHER;
  282.       } else if (strcmp(argv[mark], "2x2") == 0) {
  283.     argc--; mark++;
  284.     ditherType = Twox2_DITHER;
  285.       } else if (strcmp(argv[mark], "gray") == 0) {
  286.     argc--; mark++;
  287.     ditherType = GRAY_DITHER;
  288.       } else if (strcmp(argv[mark], "color") == 0) {
  289.     argc--; mark++;
  290.     ditherType = FULL_COLOR_DITHER;
  291.       } else if (strcmp(argv[mark], "none") == 0) {
  292.     argc--; mark++;
  293.     ditherType = NO_DITHER;
  294.       } else if (strcmp(argv[mark], "ordered") == 0) {
  295.     argc--; mark++;
  296.     ditherType = ORDERED_DITHER;
  297.       } else if (strcmp(argv[mark], "ordered2") == 0) {
  298.     argc--; mark++;
  299.     ditherType = ORDERED2_DITHER;
  300.       } else if (strcmp(argv[mark], "mbordered") == 0) {
  301.     argc--; mark++;
  302.     ditherType = MBORDERED_DITHER;
  303.       } else if (strcmp(argv[mark], "mono") == 0) {
  304.     argc--; mark++;
  305.     ditherType = MONO_DITHER;
  306.       } else if (strcmp(argv[mark], "threshold") == 0) {
  307.     argc--; mark++;
  308.     ditherType = MONO_THRESHOLD;
  309.       } else {
  310.     perror("Illegal dither option.");
  311.     usage(argv[0]);
  312.       }
  313.     } 
  314.     else if (strcmp(argv[mark], "-eachstat") == 0) {
  315.       argc--; mark++;
  316. #ifdef ANALYSIS
  317.       showEachFlag = 1;
  318. #else
  319.       fprintf(stderr, "To use -eachstat, recompile with -DANALYSIS in CFLAGS\n");
  320.       exit(1);
  321. #endif
  322.     }
  323.     else if (strcmp(argv[mark], "-shmem_off") == 0) {
  324.       argc--; mark++;
  325.       shmemFlag = 0;
  326.     }
  327.     else if (strcmp(argv[mark], "-quiet") == 0) {
  328.       argc--; mark++;
  329.       quietFlag = 1;
  330.     }
  331.     else if (strcmp(argv[mark], "-loop") == 0) {
  332.       argc--; mark++;
  333.       loopFlag = 1;
  334.     }
  335.     else if (strcmp(argv[mark], "-no_display") == 0) {
  336.       argc--; mark++;
  337.       noDisplayFlag = 1;
  338.     }
  339.     else if (strcmp(argv[mark], "-l_range") == 0) {
  340.       argc--; mark++;
  341.       LUM_RANGE = atoi(argv[mark]);
  342.       if (LUM_RANGE < 1) {
  343.     fprintf(stderr, "Illegal luminance range value: %d\n", LUM_RANGE);
  344.     exit(1);
  345.       }
  346.       argc--; mark++;
  347.     }
  348.     else if (strcmp(argv[mark], "-cr_range") == 0) {
  349.       argc--; mark++;
  350.       CR_RANGE = atoi(argv[mark]);
  351.       if (CR_RANGE < 1) {
  352.     fprintf(stderr, "Illegal cr range value: %d\n", CR_RANGE);
  353.     exit(1);
  354.       }
  355.       argc--; mark++;
  356.     }
  357.     else if (strcmp(argv[mark], "-cb_range") == 0) {
  358.       argc--; mark++;
  359.       CB_RANGE = atoi(argv[mark]);
  360.       if (CB_RANGE < 1) {
  361.     fprintf(stderr, "Illegal cb range value: %d\n", CB_RANGE);
  362.     exit(1);
  363.       }
  364.       argc--; mark++;
  365.     }
  366.     else if (argv[mark][0] == '-') {
  367.       fprintf(stderr, "Un-recognized flag %s\n",argv[mark]);
  368.       usage(argv[0]);
  369.     }
  370.     else {
  371. #ifdef OS2
  372.       /* @@@ AK, I think you mean open a binary file */
  373.       input = fopen(argv[mark], "rb");
  374. #else
  375.       input = fopen(argv[mark], "r");
  376. #endif
  377.       if (input == NULL) {
  378.     fprintf(stderr, "Could not open file %s\n", argv[mark]);
  379.     usage(argv[0]);
  380.       }
  381.       argc--; mark++;
  382.     }
  383.   }
  384.  
  385.   lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
  386.   cr_values = (int *) malloc(CR_RANGE*sizeof(int));
  387.   cb_values = (int *) malloc(CB_RANGE*sizeof(int));
  388.  
  389. #if defined(OS2)
  390.   signal(SIGBREAK, (_SigFunc) int_handler);
  391. #else
  392.   signal(SIGINT, int_handler);
  393. #endif
  394.  
  395.   init_tables();
  396.   
  397.   switch (ditherType) {
  398.     
  399.   case HYBRID_DITHER:
  400.     
  401.     InitColor();
  402.     InitHybridDither();
  403.     InitDisplay(name);
  404.     break;
  405.     
  406.     case HYBRID2_DITHER:
  407.     InitColor();
  408.     InitHybridErrorDither();
  409.     InitDisplay(name);
  410.     break;
  411.     
  412.   case FS4_DITHER:
  413.     InitColor();
  414.     InitFS4Dither();
  415.       InitDisplay(name);
  416.     break;
  417.     
  418.   case FS2_DITHER:
  419.     InitColor();
  420.     InitFS2Dither();
  421.     InitDisplay(name);
  422.     break;
  423.     
  424.   case FS2FAST_DITHER:
  425.     InitColor();
  426.     InitFS2FastDither();
  427.     InitDisplay(name);
  428.     break;
  429.     
  430.   case Twox2_DITHER:
  431.     InitColor();
  432.     Init2x2Dither();
  433.     InitDisplay(name);
  434.     PostInit2x2Dither();
  435.     break;
  436.  
  437.   case GRAY_DITHER:
  438.     InitGrayDisplay(name);
  439.     break;
  440.  
  441.   case FULL_COLOR_DITHER:
  442.     InitColorDither();
  443.     InitColorDisplay(name);
  444.     break;
  445.  
  446.   case NO_DITHER:
  447.     shmemFlag = 0;
  448.     break;
  449.  
  450.   case ORDERED_DITHER:
  451.     InitColor();
  452.     InitOrderedDither();
  453.     InitDisplay(name);
  454.     break;
  455.  
  456.   case MONO_DITHER:
  457.   case MONO_THRESHOLD:
  458.     InitMonoDisplay(name);
  459.     break;
  460.  
  461.   case ORDERED2_DITHER:
  462.     InitColor();
  463.     InitDisplay(name);
  464.     InitOrdered2Dither();
  465.     break;
  466.  
  467.   case MBORDERED_DITHER:
  468.     InitColor();
  469.     InitDisplay(name);
  470.     InitMBOrderedDither();
  471.     break;
  472.  
  473.   }
  474.  
  475. #ifdef SH_MEM
  476.     if (shmemFlag && (display != NULL)) {
  477.       if (!XShmQueryExtension(display)) {
  478.     shmemFlag = 0;
  479.     if (!quietFlag) {
  480.       fprintf(stderr, "Shared memory not supported\n");
  481.       fprintf(stderr, "Reverting to normal Xlib.\n");
  482.     }
  483.       }
  484.     }
  485. #endif
  486.  
  487.   if (setjmp(env) != 0) {
  488.  
  489.     DestroyVidStream(theStream);
  490.  
  491.     rewind(input);
  492.  
  493.     EOF_flag = 0;
  494.     curBits = 0;
  495.     bitOffset = 0;
  496.     bufLength = 0;
  497.     bitBuffer = NULL;
  498.     totNumFrames = 0;
  499. #ifdef ANALYSIS 
  500.     init_stats();
  501. #endif
  502.  
  503.   }
  504.  
  505.   theStream = NewVidStream(BUF_LENGTH);
  506.  
  507.  
  508.   mpegVidRsrc(0, theStream);
  509.  
  510.   if (ditherType == Twox2_DITHER) i = 2;
  511.   else i = 1;  
  512.  
  513.   ResizeDisplay(curVidStream->h_size*i, curVidStream->v_size*i);
  514.  
  515.   realTimeStart = ReadSysClock();
  516.  
  517.   while (1) mpegVidRsrc(0, theStream);
  518. }
  519.  
  520.  
  521. /*
  522.  *--------------------------------------------------------------
  523.  *
  524.  * usage --
  525.  *
  526.  *    Print mpeg_play usage
  527.  *
  528.  * Results:
  529.  *    None.
  530.  *
  531.  * Side effects:
  532.  *    exits with a return value -1
  533.  *
  534.  *--------------------------------------------------------------
  535.  */
  536.  
  537. void
  538. usage(s)
  539. char *s;    /* program name */
  540. {
  541.     fprintf(stderr, "Usage:\n");
  542.     fprintf(stderr, "mpeg_play\n");
  543.     fprintf(stderr, "          [-nob]\n");
  544.     fprintf(stderr, "          [-nop]\n");
  545.     fprintf(stderr, "          [-dither {ordered|ordered2|mbordered|fs4|fs2|fs2fast|hybrid|\n");
  546. #ifdef OS2
  547.     /* @@@ AK, Full colour dither not supported, no 24 bit display provided */
  548.     fprintf(stderr, "                    hybrid2|2x2|gray|none|mono|threshold}]\n");
  549. #else
  550.     fprintf(stderr, "                    hybrid2|2x2|gray|color|none|mono|threshold}]\n");
  551. #endif
  552.     fprintf(stderr, "          [-loop]\n");
  553.     fprintf(stderr, "          [-eachstat]\n");
  554.     fprintf(stderr, "          [-no_display]\n");
  555.     fprintf(stderr, "          [-quiet]\n");
  556.     fprintf(stderr, "          file_name\n");
  557.     exit (-1);
  558. }
  559.  
  560.  
  561.  
  562. /*
  563.  *--------------------------------------------------------------
  564.  *
  565.  * DoDitherImage --
  566.  *
  567.  *    Called when image needs to be dithered. Selects correct
  568.  *      dither routine based on info in ditherType.
  569.  *
  570.  * Results:
  571.  *    None.
  572.  *
  573.  * Side effects:
  574.  *    None.
  575.  *
  576.  *--------------------------------------------------------------
  577.  */
  578.  
  579. void
  580. DoDitherImage(l, Cr, Cb, disp, h, w) 
  581. unsigned char *l, *Cr, *Cb, *disp;
  582. int h,w;
  583. {
  584.  
  585.   switch(ditherType) {
  586.   case HYBRID_DITHER:
  587.     HybridDitherImage(l, Cr, Cb, disp, h, w);
  588.     break;
  589.  
  590.   case HYBRID2_DITHER:
  591.     HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
  592.     break;
  593.  
  594.   case FS2FAST_DITHER:
  595.     FS2FastDitherImage(l, Cr, Cb, disp, h, w);
  596.     break;
  597.  
  598.   case FS2_DITHER:
  599.     FS2DitherImage(l, Cr, Cb, disp, h, w);
  600.     break;
  601.  
  602.   case FS4_DITHER:
  603.     FS4DitherImage(l, Cr, Cb, disp, h, w);
  604.     break;
  605.  
  606.   case Twox2_DITHER:
  607.     Twox2DitherImage(l, Cr, Cb, disp, h, w);
  608.     break;
  609.  
  610.   case FULL_COLOR_DITHER:
  611.     ColorDitherImage(l, Cr, Cb, disp, h, w);
  612.     break;
  613.  
  614.   case GRAY_DITHER:
  615.     GrayDitherImage(l, Cr, Cb, disp, h, w);
  616.     break;
  617.  
  618.   case NO_DITHER:
  619.     break;
  620.  
  621.   case ORDERED_DITHER:
  622.     OrderedDitherImage(l, Cr, Cb, disp, h, w);
  623.     break;
  624.  
  625.   case MONO_DITHER:
  626.     MonoDitherImage(l, Cr, Cb, disp, h, w);
  627.     break;
  628.  
  629.   case MONO_THRESHOLD:
  630.     MonoThresholdImage(l, Cr, Cb, disp, h, w);
  631.     break;
  632.  
  633.   case ORDERED2_DITHER:
  634.     Ordered2DitherImage(l, Cr, Cb, disp, h, w);
  635.     break;
  636.  
  637.   case MBORDERED_DITHER:
  638.     MBOrderedDitherImage(l, Cr, Cb, disp, h, w);
  639.     break;
  640.   }
  641. }
  642.